﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using Bainx.Extend;
using Bainx.WPF.Extend;

namespace WM360Client
{
    public class WPFBaseWindow : Window
    {
        /// <summary>
        /// 统一子类窗体的皮肤
        /// </summary>
        public static Bainx.WPF.Extend.Skin Skin;
        static WPFBaseWindow()
        {
            Skin = new Skin(Application.Current.Resources);
            
        }

        #region //私有成员
        private Visibility minVisibility = Visibility.Visible,
                            maxVisibility = Visibility.Visible,
                            closeVisibility = Visibility.Visible,
                         //   iconVisibility = Visibility.Visible,
                         //   titleVisibility = Visibility.Visible,
                            headAreaVisibility = Visibility.Visible,
                            footAreaVisibility = Visibility.Visible,
                         //   statuVisibility = Visibility.Visible,
                            resizeVisibility = Visibility.Visible;

        private Button winMin, winMax, winClose;

        private Border winHeadBorder, winFootBorder;        

        private Border winBorder, winBackColor, winIconArea, winTitleArea;

        private Grid winLayoutRoot, winResizeGrid, winBodyGrid, winHeadGrid, winFootGrid;

        private ControlTemplate windowTemplate;

        private string[] ResizeRectangle = new string[] {   "ResizeTopLeft",    "ResizeTop",    "ResizeTopRight",
                                                    "ResizeLeft",                           "ResizeRight",
                                                    "ResizeBottomLeft",    "ResizeBottom",    "ResizeBottomRight"
                                                };
        #endregion

        #region //属性
        /// <summary>
        /// 获取或设置窗体大小
        /// </summary>
        public Size Size
        {
            get { return new Size(Width, Height); }
            set
            {
                if (!value.IsEmpty)
                {
                    Width = value.Width;
                    Height = value.Height;
                }
            }
        }
        /// <summary>
        /// 获取或设置窗体位置
        /// </summary>
        public Point Location
        {
            get { return new Point(Left, Top); }
            set
            {
                Left = value.X;
                Top = value.Y;
            }
        }
        /// <summary>
        /// 窗体的暗边框(外边框)
        /// </summary>
        public Border DarkBorder { get { return winBorder; } }
        /// <summary>
        /// 窗体的亮边框(内边框)
        /// </summary>
        public Border LightBorder { get { return winBackColor; } }
        /// <summary>
        /// 窗体的底层背景(外边框内背景)
        /// </summary>
        public Brush DarkBackground
        {
            get { return winBorder.Background; }
            set { winBorder.Background = value; }
        }
        /// <summary>
        /// 窗体顶层背景
        /// </summary>
        public new Brush Background
        {
            get { return winBackColor.Background; }
            set { winBackColor.Background = value; }
        }
        /// <summary>
        /// 窗体设置圆角
        /// </summary>
        public CornerRadius CornerRadius
        {
            get { return winBorder.CornerRadius; }
            set 
            {
                winBorder.CornerRadius = value;
                winBackColor.CornerRadius = value;
                winHeadBorder.CornerRadius = new CornerRadius(value.TopLeft, value.TopRight, 0, 0);
                winFootBorder.CornerRadius = new CornerRadius(0, 0, value.BottomLeft, value.BottomRight);
            }
        }

        /// <summary>
        /// 头部区域背景,窗体Loaded前设置无效
        /// </summary>
        public Brush HeadAreaBackground
        {
            get { return winHeadBorder.Background; }
            set
            {
                if (winHeadBorder != null)
                    winHeadBorder.Background = value;
            }
        }
        /// <summary>
        /// 底部区域背景,窗体Loaded前设置无效
        /// </summary>
        public Brush FootAreaBackground
        {
            get { return winFootBorder.Background; }
            set
            {
                if (winFootBorder != null)
                    winFootBorder.Background = value;
            }
        }
        
        /// <summary>
        /// 获取或设置最大化按钮的显示状态
        /// </summary>
        public Visibility MaximizeBox
        {
            get { return winMax.Visibility; }
            set 
            {
                if (winMax != null)
                    winMax.Visibility = value;
                maxVisibility = value;
            }
        }
        /// <summary>
        /// 获取或设置最小化按钮的显示状态
        /// </summary>
        public Visibility MinimizeBox
        {
            get { return winMin.Visibility; }
            set 
            {
                if (winMin != null)
                    winMin.Visibility = value;
                minVisibility = value;
            }
        }
        /// <summary>
        /// 获取或设置关闭窗体按钮的显示状态
        /// </summary>
        public Visibility CloseBox
        {
            get { return winClose.Visibility; }
            set 
            {
                if (winClose != null)
                    winClose.Visibility = value;
                closeVisibility = value;
            }
        }
        /// <summary>
        /// 头部区域,包括标题,ICON,最小化,最大化,关闭按钮
        /// 设置 Hidden或 Collapsed 值后将影响窗口拖动
        /// 如需拖动窗体,请将控件的MouseMove事件设置成DragMoveWindow
        /// </summary>
        public Visibility HeadArea
        {
            get { return winHeadBorder.Visibility; }
            set
            {
                if (winHeadBorder != null)
                    winHeadBorder.Visibility = value;
                headAreaVisibility = value;
            }
        }

        public Visibility FootArea
        {
            get { return winFootBorder.Visibility; }
            set
            {
                if (winFootBorder != null)
                    winFootBorder.Visibility = value;
                footAreaVisibility = value;
            }
        }

        public new ResizeMode ResizeMode
        {
            get { return base.ResizeMode; }
            set 
            {
                switch (value)
                { 
                    case System.Windows.ResizeMode.CanMinimize:
                        MinimizeBox = System.Windows.Visibility.Visible;
                        MaximizeBox = System.Windows.Visibility.Visible;
                        CloseBox = System.Windows.Visibility.Visible;
                        break;
                    case System.Windows.ResizeMode.CanResize:
                         MinimizeBox = System.Windows.Visibility.Visible;
                        MaximizeBox = System.Windows.Visibility.Visible;
                        CloseBox = System.Windows.Visibility.Visible;
                        break;
                    case System.Windows.ResizeMode.CanResizeWithGrip:
                         MinimizeBox = System.Windows.Visibility.Visible;
                        MaximizeBox = System.Windows.Visibility.Visible;
                        CloseBox = System.Windows.Visibility.Visible;
                        break;
                    case System.Windows.ResizeMode.NoResize:
                        MinimizeBox = System.Windows.Visibility.Collapsed;
                         MaximizeBox = System.Windows.Visibility.Collapsed;
                        CloseBox = System.Windows.Visibility.Visible;
                        resizeVisibility = System.Windows.Visibility.Collapsed;
                        break;
                }
            }
        }

        /// <summary>
        /// 获取或设置是否可能从边框上调整窗体大小,
        /// 子类在重载LoadStyleConfigure方法时设置或窗体Loaded事件前设置有效,
        /// </summary>
        public bool CanResize
        {
            get { return resizeVisibility == Visibility.Visible; }
            protected set { resizeVisibility = value ? Visibility.Visible : Visibility.Collapsed; }
        }

        #endregion

        #region //事件

        /// <summary>
        /// 事件:鼠标左键拖动窗体时发生
        /// </summary>
        public event MouseEventHandler DragMoveWindowBegin;
        /// <summary>
        /// 事件鼠标拖动窗体结束时发生
        /// </summary>
        public event MouseEventHandler DragMoveWindowEnd;

        #endregion


        public WPFBaseWindow()
        {
            Initialize();
            
            this.MaxWidth = System.Windows.SystemParameters.FullPrimaryScreenWidth + 10;
            this.MaxHeight = System.Windows.SystemParameters.FullPrimaryScreenHeight + 33;
            

            this.SourceInitialized += delegate(object sender, EventArgs e)
            {
                this._HwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
            };
            
            
        }

        private void Initialize()
        {
            InitializeStyle();
            this.Loaded += delegate
            {
                this.InvokeIfNeeded(() => InvokeInitializeEvent(), System.Windows.Threading.DispatcherPriority.Send);
            };
        }
        private void InvokeInitializeEvent()
        {
            LoadStyleConfigure();
            InitializeEvent();
            LoadStyleComponent();
        }

        /// <summary>
        /// 子类重载此方法,实现对窗体样式的初始控制,无须调用父类方法
        /// </summary>
        protected virtual void LoadStyleComponent() { }
        /// <summary>
        /// 子类重载此方法,实现对窗体样式的初始配置,无须调用父类方法
        /// </summary>
        protected virtual void LoadStyleConfigure() { }
        
        
        
        private  void InitializeEvent()
        {
            windowTemplate = (ControlTemplate)Application.Current.Resources["WindowTemplateKey"];

            winLayoutRoot = getEleMentByName<Grid>("WinLayoutRoot");

            winHeadAreaSupport();

            winFootAreaSupport();

            winBorderSupport();

            winBackColorSupport();

            winIconAreaSupport();

            winTitleAreaSupport();

            winBodyGridSupport();

            winHeadGridSupport();

            winFootGridSupport();

            winMinSupport();

            winMaxSupport();

            winCloseSupport();

            ResizeSupport();

            if (headAreaVisibility == System.Windows.Visibility.Collapsed)
            {
               // winLayoutRoot.RowDefinitions[1].Height = new GridLength(winLayoutRoot.RowDefinitions[1].Height.Value + winLayoutRoot.RowDefinitions[0].Height.Value - 1);
                winLayoutRoot.RowDefinitions[0].Height = new GridLength(1);
            }
            if (footAreaVisibility == System.Windows.Visibility.Collapsed)
            {
                //winLayoutRoot.RowDefinitions[1].Height = new GridLength(winLayoutRoot.RowDefinitions[1].Height.Value + winLayoutRoot.RowDefinitions[2].Height.Value - 1);               
                winLayoutRoot.RowDefinitions[2].Height = new GridLength(1);
            }

            //
        }

        private void InitializeStyle()
        {
            this.Style = (Style)Application.Current.Resources["DefaultWindowStyle"];
        }

        private T getEleMentByName<T>(string Name)
        {
            T ret = (T)windowTemplate.FindName(Name, this);
            if (ret == null) throw new Exception(Name + "不存在于此窗体模板中");
            return ret;
        }

        #region //由模板得到的控件支持
        private void winHeadAreaSupport()
        {
            winHeadBorder = getEleMentByName<Border>("WinHeadBorder");
            winHeadBorder.Visibility = headAreaVisibility;
            winHeadBorder.MouseMove += new MouseEventHandler(DragMoveWindow);
            if (maxVisibility == System.Windows.Visibility.Visible)
                winHeadBorder.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
                {
                    if (e.ClickCount >= 2)
                    {
                        winMax.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                    }
                };
        }
        private void winFootAreaSupport()
        {
            winFootBorder = getEleMentByName<Border>("WinFootBorder");
            winFootBorder.Visibility = footAreaVisibility;          
        }
        private void winBorderSupport()
        {
            winBorder = getEleMentByName<Border>("WinBorder");
        }
        private void winBackColorSupport()
        {
            winBackColor = getEleMentByName<Border>("WinBackColor");
        }
        private void winIconAreaSupport()
        {
            winIconArea = getEleMentByName<Border>("WinIconArea");
        }
        private void winTitleAreaSupport()
        {
            winTitleArea = getEleMentByName<Border>("WinTitleArea");
        }
        private void winBodyGridSupport()
        {
            winBodyGrid = getEleMentByName<Grid>("WinBodyGrid");
        }
        private void winHeadGridSupport()
        {
            winHeadGrid = getEleMentByName<Grid>("WinHeadGrid");
        }
        private void winFootGridSupport()
        {
            winFootGrid = getEleMentByName<Grid>("WinFootGrid");
        }
        private void winCloseSupport()
        {
            winClose = (Button)windowTemplate.FindName("WinClose", this);
            winClose.Visibility = closeVisibility;
            winClose.Click += new RoutedEventHandler(WinClose_Click);
        }
        private void winMinSupport()
        {
            winMin = (Button)windowTemplate.FindName("WinMin", this);
            winMin.Visibility = minVisibility;
            winMin.Click += new RoutedEventHandler(WinMin_Click);           
        }
        private void winMaxSupport()
        {
            winMax = (Button)windowTemplate.FindName("WinMax", this);
            winMax.Visibility = maxVisibility;
            winMax.Click += new RoutedEventHandler(WinMax_Click);
        }
        private void ResizeSupport()
        {
            winResizeGrid = getEleMentByName<Grid>("WinResizeGrid");
            winResizeGrid.Visibility = resizeVisibility;
            foreach (string item in ResizeRectangle)
            {
                Rectangle RR = getEleMentByName<Rectangle>(item);
                RR.MouseMove += new MouseEventHandler(ResizePressed);
                RR.MouseDown += new MouseButtonEventHandler(ResizePressed);
                RR.MouseLeave += new MouseEventHandler(ResizeMouseLeave);
            }
        }
        #endregion //由模板得到的控件支持

        #region //事件处理
        /// <summary>
        /// 拖动窗体
        /// </summary>
        protected virtual void DragMoveWindow(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && WindowState == System.Windows.WindowState.Normal)
            {
                if (DragMoveWindowBegin != null) DragMoveWindowBegin(sender, e);
                this.DragMove();
                if (DragMoveWindowEnd != null) DragMoveWindowEnd(sender, e);
            }
        }
        /// <summary>
        /// 最小化窗体
        /// </summary>
        protected virtual void WinMin_Click(object sender, RoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized;            
        }        
        /// <summary>
        /// 最大化窗体
        /// </summary>
        protected virtual void WinMax_Click(object sender, RoutedEventArgs e)
        {
            this.WindowState = (this.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal);                      
        }
        /// <summary>
        /// 关闭窗体
        /// </summary>
        protected virtual void WinClose_Click(object sender, RoutedEventArgs e)
        {
            //this.Close();
            this.InvokeIfNeeded(() => this.Close(), System.Windows.Threading.DispatcherPriority.Background);
        }
        #endregion

        #region //窗体控制
        private const int WM_SYSCOMMAND = 0x112;
        private HwndSource _HwndSource;

        private Dictionary<ResizeDirection, System.Windows.Input.Cursor> cursors = new Dictionary<ResizeDirection, Cursor>
        {
            {ResizeDirection.Top, System.Windows.Input.Cursors.SizeNS},
            {ResizeDirection.Bottom, System.Windows.Input.Cursors.SizeNS},
            {ResizeDirection.Left, System.Windows.Input.Cursors.SizeWE},
            {ResizeDirection.Right, System.Windows.Input.Cursors.SizeWE},
            {ResizeDirection.TopLeft, System.Windows.Input.Cursors.SizeNWSE},
            {ResizeDirection.BottomRight, System.Windows.Input.Cursors.SizeNWSE},
            {ResizeDirection.TopRight, System.Windows.Input.Cursors.SizeNESW},
            {ResizeDirection.BottomLeft, System.Windows.Input.Cursors.SizeNESW}
        };

        public enum ResizeDirection
        {
            Left = 1,
            Right = 2,
            Top = 3,
            TopLeft = 4,
            TopRight = 5,
            Bottom = 6,
            BottomLeft = 7,
            BottomRight = 8,
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);



        ///// <summary>
        ///// 鼠标在窗体上移动，子类须执行父类方法。
        ///// </summary>
        //protected virtual void Window_MouseMove(object sender, MouseEventArgs e)
        //{
        //    if (Mouse.LeftButton != MouseButtonState.Pressed)
        //    {
        //        FrameworkElement element = e.OriginalSource as FrameworkElement;
        //        if (element != null && !element.Name.Contains("Resize"))
        //            this.Cursor = System.Windows.Input.Cursors.Arrow;

        //    }
        //}
        void ResizeMouseLeave(object sender, MouseEventArgs e)
        {
            this.Cursor = System.Windows.Input.Cursors.Arrow;
        }
        private  void ResizePressed(object sender, MouseEventArgs e)
        {            

            FrameworkElement element = sender as FrameworkElement;
            ResizeDirection direction = (ResizeDirection)Enum.Parse(typeof(ResizeDirection), element.Name.Replace("Resize", ""));

            this.Cursor = cursors[direction];

            if (e.LeftButton == MouseButtonState.Pressed)
                ResizeWindow(direction);
        }
        /// <summary>
        /// 改变窗体大小，子类须执行父类方法。
        /// </summary>
        protected virtual void ResizeWindow(ResizeDirection direction)
        {
            SendMessage(_HwndSource.Handle, WM_SYSCOMMAND, (IntPtr)(61440 + direction), IntPtr.Zero);            
        }

        #endregion //窗体控制        
        /// <summary>
        /// 载入一个XAML资源文件来更改皮肤
        /// </summary>
        /// <param name="resourceLocator">一个映射到相对 XAML 文件的 System.Uri</param>
        public virtual void SkinChange(Uri resourceLocator)
        {          
            ResourceDictionary resource = (ResourceDictionary)Application.LoadComponent(resourceLocator);           
            Application.Current.Resources.MergedDictionaries.Clear();           
            Application.Current.Resources.MergedDictionaries.Add(resource);
        }


    }
   
}
